﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.IO;
using System.Reflection;
using System.Collections;
using System.Windows.Forms;

namespace RungSoft.RungEBookMaker.Providers
{
    internal class StaticFunction
    {
        internal const string SYSTEM_NAME = "RungSoft EBook";

        internal const string WINDOWS_RETURN = "\r\n";
        internal const string SYMBIAN_RETURN = "\u2029";
        internal const string SYMBIAN_SPACE = "　";

        private static List<SWidthData> WidthData_S60 = new List<SWidthData>();
        private static List<SWidthData> WidthData_SP = new List<SWidthData>();

        [StructLayout(LayoutKind.Sequential)]
        private struct SWidthData
        {
            public byte FontSize;
            public ushort RngFrom;
            public ushort RngTo;
            public uint vCount;
            public byte[] Value;
        }

        private static BinaryReader GetBinary(string fullFilePath)
        {
            if (File.Exists(fullFilePath))
            {
                using (FileStream input = new FileStream(fullFilePath, FileMode.Open, FileAccess.Read))
                {
                    return new BinaryReader(input);
                }
            }
            else
                throw (new FileNotFoundException(string.Format("无法找到【{0}】文件。", fullFilePath)));
        }

        private static List<SWidthData> GetWidthDataByReader(BinaryReader reader, byte fontSize)
        {
            List<SWidthData> result = new List<SWidthData>();

            while (reader.BaseStream.Position < reader.BaseStream.Length)
            {
                SWidthData data = new SWidthData();

                data.RngFrom = reader.ReadUInt16();
                data.RngTo = reader.ReadUInt16();
                data.vCount = reader.ReadUInt16();
                data.Value = reader.ReadBytes((int)data.vCount);
                data.FontSize = fontSize;

                result.Add(data);
            }

            return result;
        }

        private static void GetWidthData_S60()
        {
            List<SWidthData> s16WD = WidthData_S60.FindAll(delegate(SWidthData d) { return d.FontSize == 0x10; });
            if (s16WD == null || s16WD.Count == 0)
            {
                string pathS16 = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase.Remove(0, 8)) + @"\FontWidthData\S60CHS.S16.wdt";

                using (BinaryReader reader = GetBinary(pathS16))
                {
                    WidthData_S60.AddRange(GetWidthDataByReader(reader, 0x10));
                }
            }

            List<SWidthData> s12WD = WidthData_S60.FindAll(delegate(SWidthData d) { return d.FontSize == 12; });
            if (s12WD == null || s12WD.Count == 0)
            {
                string pathS12 = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase.Remove(0, 8)) + @"\FontWidthData\S60CHS.S12.wdt";

                using (BinaryReader reader = GetBinary(pathS12))
                {
                    WidthData_S60.AddRange(GetWidthDataByReader(reader, 12));
                }
            }
        }

        private static void GetWidthData_SP()
        {
            List<SWidthData> spWD = WidthData_SP.FindAll(delegate(SWidthData d) { return d.FontSize == 0x10; });
            if (spWD == null || spWD.Count == 0)
            {
                for (int i = 0x10; i < 0x11; i++)
                {
                    string path = (Assembly.GetExecutingAssembly().CodeBase.Remove(0, 8) + @"\FontWidthData\sunfon.s") + i.ToString() + ".wdt";

                    using (BinaryReader reader = GetBinary(path))
                    {
                        WidthData_S60.AddRange(GetWidthDataByReader(reader, (byte)i));
                    }
                }
            }
        }

        internal static byte CharWidth_S60(string Char, byte pFontSize)
        {
            ushort num = Char[0];
            for (int i = 0; i < WidthData_S60.Count; i++)
            {
                SWidthData data = WidthData_S60[i];
                if (((data.FontSize == pFontSize) && (num >= data.RngFrom)) && (num <= data.RngTo))
                {
                    if (data.vCount == 1)
                    {
                        return data.Value[0];
                    }
                    return data.Value[num - data.RngFrom];
                }
            }
            return pFontSize;
        }

        private byte CharWidth_SP(string Char, byte pFontSize)
        {
            ushort num = Char[0];
            for (int i = 0; i < WidthData_SP.Count; i++)
            {
                SWidthData data = (SWidthData)WidthData_SP[i];
                if (((data.FontSize == pFontSize) && (num >= data.RngFrom)) && (num <= data.RngTo))
                {
                    if (data.vCount == 1)
                    {
                        return data.Value[0];
                    }
                    return data.Value[num - data.RngFrom];
                }
            }
            return pFontSize;
        }

        private void ParseOnePage(uint pPageNumber, byte pFontSize, uint pScreenWidth, ref ArrayList pPageoff, byte PID)
        {
        }

        private bool GetPageOffsetS60(byte size, uint actual_width, out uint[] result)
        {
            result = null;
            return true;
        }

        internal static void ShowMessageBox(string msg)
        {
            MessageBox.Show(msg, SYSTEM_NAME);
        }
    }
}
